import {removeUnit} from 'plain-utils/string/removeUnit';
import {$$loading} from "plain-ui";
import {defer} from 'plain-utils/utils/defer';

/**
 * 主题样式变量中，需要排除的样式变量(就是不可以编辑的变量)
 * @author  韦胜健
 * @date    2021/1/28 14:36
 */
const excludeVariables = [
    'font',
    'transitionFlexible',
    'transition',
    'transition2',
    'boxshadow',
    'boxshadowColor',
    'popperRadius',
]

/**
 * 获取Sass依赖
 * @author  韦胜健
 * @date    2021/1/27 20:28
 */
const loadSass = (() => {
    let promise: Promise<{ compile: (code: string, callback: (result: { text: string }) => void) => void }>;
    return () => {
        if (!promise) {
            promise = new Promise<any>((resolve, reject) => {
                const loading = $$loading.bar()
                const el = document.createElement('script')
                el.setAttribute('src', `http://martsforever-demo.gitee.io/martsforever-assets/sass.sync.min.js`)
                el.setAttribute('id', 'sass')
                el.onload = () => {
                    resolve((window as any)['Sass'])
                    loading.done()
                }
                el.onerror = e => {
                    loading.fail()
                    reject(e)
                }
                document.body.appendChild(el)
            })
        }
        return promise
    }
})();

/**
 * 编译scss代码
 * @author  韦胜健
 * @date    2021/1/27 20:31
 */
const compile = async (code: string) => {
    const dfd = defer<string>()
    const Sass = await loadSass()
    Sass.compile(code, result => dfd.resolve(result.text))
    return dfd.promise
}

/**
 * 解析globalImport代码
 * @author  韦胜健
 * @date    2021/1/28 14:36
 */
function decodeGlobalImport(globalImport: string) {
    const match = globalImport.match(/\$theme-default(?:(?:.|\r|\n)*?)'':\((?:(?:.|\r|\n)*?)(\S(?:.|\r|\n)*?)\s\)/)
    if (!match) {
        console.log(globalImport)
        throw new Error('解析 globalImport 失败，无法匹配到 theme-default！')
    }
    const lines = match[1].split(/[\r\n]/)
    /*默认的主题样式表单编辑对象*/
    const defaultEditData: Record<string, string> = {}
    /*默认的变量信息数组*/
    const defaultVariables: { key: string, value: string, comments: string }[] = []
    lines.filter(line => !!line.trim()).forEach(line => {
        let [key, value, comments] = line.split(/(?::|,(?!.*,))/)
        key = key.trim()
        value = value.trim()
        if (/\d*px/.test(value)) {
            value = removeUnit(value)
        }
        comments = comments.trim()
        if (excludeVariables.indexOf(key) === -1) {
            defaultEditData[key] = value
        }
        defaultVariables.push({key, value, comments})
    })
    return {
        defaultEditData,            // 主题变量集合，key为变量名称，value为变量值（通过excludeVariables移除了部分变量）
        defaultVariables,           // 主题变量数组，是完整的数据
    }
}

/**
 * 获取用来编译scss代码的编译器
 * @author  韦胜健
 * @date    2021/1/28 14:37
 */
function getThemeCompiler(globalImport: string, packagesScss: { name: string, seq: number, codes: string[] }[], externalScssCode: string) {
    const themeBlueMatch = (globalImport).match(/\$theme-blue:[.\s]*\(((?:.|\r|\n)*?)\);/)
    if (!themeBlueMatch) {
        console.log(globalImport)
        throw new Error('解析 globalImport 失败，无法匹配到 theme-blue！')
    }
    const [m, g1] = themeBlueMatch

    /**
     * 编译获取scss主题变量文件
     * @author  韦胜健
     * @date    2021/1/28 14:38
     */
    const generateVariables = (themeData: Record<string, string>, themeName: string) => {
        const themeString = Object.entries(themeData).map(([key, value]) => {
            let val = value as string | number
            if (/^\d*$/.test(String(val))) {
                val = `${val}px`
            }
            return `${key}:${val},`
        }).join('\n')
        return m.replace(g1, `
                '${themeName}':(
                    ${themeString}
                )
            `)
    }

    /**
     * 编译获取css主题色文件
     * @author  韦胜健
     * @date    2021/1/28 14:38
     */
    const generateCssFile = (themeData: Record<string, string>, themeName: string) => {
        const theme = generateVariables(themeData, themeName)
        let newGlobalImport = globalImport.replace(m, theme)
        if (themeName.trim() !== '') {
            newGlobalImport = newGlobalImport.replace('$generate_default: true;', '$generate_default: false;')
        }
        let scss = `${newGlobalImport} ${packagesScss.map(({codes}) => codes.join('')).join('')} ${externalScssCode}`
        return compile(scss)
    }

    return {
        generateCssFile,
        generateVariables,
    }
}

/**
 * 配置主题配置对象
 * @author  韦胜健
 * @date    2021/1/28 14:38
 */
export async function getConfiguration() {
    const themeData = (await import('plain-ui/src/styles/data/scan.scss.json')).default as any as {
        globalImport: string,
        packagesScss: { name: string, seq: number, codes: string[] }[]
    }
    const externalThemeData = (await import('src/scan.scss.json')).default as any as string[]
    const {defaultEditData, defaultVariables} = decodeGlobalImport(themeData.globalImport)
    const {generateVariables, generateCssFile} = getThemeCompiler(themeData.globalImport, themeData.packagesScss, externalThemeData.join('\n'))
    return {
        defaultEditData,
        defaultVariables,
        generateVariables,
        generateCssFile,
    }
}
